
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <osal/osal.h>
#include<api/libsi/psi_pat.h>
#include <api/libsi/si_eit.h>
// Gavim
//#include <api/libtsi/si_monitor.h>
#include <api/libtsi/si_descriptor.h>
#include <api/libsi/si_desc_ter_delivery.h>
#include <api/libsi/si_nit.h>
#include <api/libsi/si_service_type.h>
#include <api/libpub/lib_as.h>
#include "win_com.h"
#include "ap_thailand_monitor.h"

static UINT32 g_thai_nit_monitor = INVALID_SIM_ID;
static UINT32 g_thai_sdt_monitor = INVALID_SIM_ID;
static UINT32 g_thai_nit_crc32 = 0;
static UINT32 g_thai_sdt_crc32 = 0;
static thai_lcn_list g_thai_chan_list = {0};
static thai_sdt_serv_list g_thai_sdt_slist = {0};
extern P_NODE playing_pnode;
static thai_q_mng g_thai_section_q;
BOOL   g_thai_q_init = FALSE;

int LCL_Verion = 0;
int nDoLCNForeign = 0;
#define MAX_LOCK_CNT 100
int ntp_id_Cnt = 0;
UINT32 g_tp_id[MAX_LOCK_CNT];
UINT16 g_level[MAX_LOCK_CNT];
UINT16 g_islock[MAX_LOCK_CNT];

#define in_range(c, lo, up)  ((unsigned char)c >= lo && (unsigned char)c <= up)
#define isprint(c)           in_range(c, 0x20, 0x7f)
thai_lcn_list_info *AOV_ch_list = NULL;

//
static UINT8 *ap_thai_queue_get(INT32 *data_len);
static void ap_thai_queue_init()
{
    int i = 0;
    
    if (g_thai_q_init == TRUE)
    {
        return;
    }

    //g_thai_section_q.count = 0;
    g_thai_section_q.read_idx = 0;
    g_thai_section_q.write_idx = 0;

    for (i=0; i<MAX_THAI_SECTION_NUM; i++)
    {
        memset(&g_thai_section_q.sections[i], 0, sizeof(thai_section_q));
    }

    g_thai_q_init = TRUE;
}

static void ap_thai_queue_free()
{
    INT32 length;
    UINT8 *section;

    while ((section = ap_thai_queue_get(&length)) != NULL)
    {
        if (section)
        {
            free(section);
            section = NULL;
        }
    }
}
static INT32 ap_thai_queue_next_write()
{
    INT32 next_idx = -1;
    
    if (g_thai_section_q.read_idx == g_thai_section_q.write_idx)
        next_idx = g_thai_section_q.write_idx;
    else if (((g_thai_section_q.write_idx+1)%MAX_THAI_SECTION_NUM) != g_thai_section_q.read_idx)
        next_idx = g_thai_section_q.write_idx;

    return next_idx;
}

static INT32 ap_thai_queue_next_read()
{
    INT32 next_idx = -1;

    if (g_thai_section_q.read_idx != g_thai_section_q.write_idx)
        next_idx = g_thai_section_q.read_idx;

    return next_idx;
}

static BOOL ap_thai_queue_put(UINT8 *data, INT32 data_len)
{
    BOOL ret = FALSE;
    INT32 idx = -1;

    if ((data == NULL) || (data_len <= 0))
        return ret;
   
    if (g_thai_q_init == FALSE)
        ap_thai_queue_init();

    idx = ap_thai_queue_next_write();
    
    if (idx < 0)
        return ret;

    g_thai_section_q.sections[idx].length = data_len;
    g_thai_section_q.sections[idx].section = data;

    g_thai_section_q.write_idx = (g_thai_section_q.write_idx+1)%MAX_THAI_SECTION_NUM;

    ret = TRUE;
    return ret;
}

static UINT8 *ap_thai_queue_get(INT32 *data_len)
{
    INT32 idx = 1;
    UINT8 *ret = NULL;

    *data_len = 0;

    idx = ap_thai_queue_next_read();

    if (idx < 0)
        return ret;

    *data_len = g_thai_section_q.sections[idx].length;
    ret = g_thai_section_q.sections[idx].section;

    g_thai_section_q.sections[idx].length = 0;
    g_thai_section_q.sections[idx].section = NULL;
    
    g_thai_section_q.read_idx = (g_thai_section_q.read_idx + 1)%MAX_THAI_SECTION_NUM;
    
    return ret;
}

static void dump_section(UINT8 *section, INT32 length)
{
    int i=0; 
    
    for (i=0; i<length; i++)
    {
        if ((i!= 0) && (i%16)==0)
            thai_ttc_print("\n");

        thai_ttc_print("%02X ", section[i]);
    }

}
static BOOL ap_thai_get_current_tp(T_NODE *tnode)
{
    BOOL ret = FALSE;

    if (tnode == NULL)
        return ret;
    
    if (DB_SUCCES == get_tp_by_id(playing_pnode.tp_id, tnode))
        ret = TRUE;
        
    return ret;
}
static INT32 ap_thai_nit_callback(UINT8 *section, INT32 length, UINT32 param)
{
    UINT8 *data = NULL;
    INT32 i = 0;
    
    if ((section == NULL) || (length <= 0) || (section[0] != PSI_NIT_TABLE_ID))
        return -1;

    data = malloc(length);
    if (data != NULL)
    {
        memcpy(data, section, length);

        // try to put into queue 3 time
        for (i=0; i<3; i++)
        {
            if (ap_thai_queue_put(data, length))
                break;
        }
        if (i == 3)
        {
            free(data);
            data = NULL;
        }
    }

    // send msg to notify ctrl task process data
    ap_send_msg(CTRL_MSG_SUBTYPE_CMD_THAI_SECTION_ARRIVED, 0, 0);
    return 0;
}
UINT32 ap_thai_nit_monitor_start(struct dmx_device *dmx)
{
    UINT32 ret = INVALID_SIM_ID;
    if (g_thai_nit_monitor != INVALID_SIM_ID)
        return g_thai_nit_monitor;

    ret = sim_start_monitor(dmx, MONITE_TB_NIT, 0x0010, 0);

    if (ret == INVALID_SIM_ID)
        return ret;


    g_thai_nit_monitor = ret;

    if (sim_register_scb(g_thai_nit_monitor, ap_thai_nit_callback, NULL) != SUCCESS)
    {
        ap_thai_nit_monitor_stop();
        g_thai_nit_monitor = INVALID_SIM_ID;
        return INVALID_SIM_ID;
    }

    return ret;
}

void ap_thai_nit_monitor_stop()
{

    if (INVALID_SIM_ID != g_thai_nit_monitor)
    {
        sim_unregister_scb(g_thai_nit_monitor, ap_thai_nit_callback);
        sim_stop_monitor(g_thai_nit_monitor);
        g_thai_nit_crc32 = 0;
        g_thai_nit_monitor = INVALID_SIM_ID;
    }
}

static INT32 ap_thai_sdt_callback(UINT8 *section, INT32 length, UINT32 param)
{
    UINT8 *data = NULL;
    INT32 i = 0;

    
    if ((section == NULL) || (length <= 0) || (section[0] != PSI_SDT_TABLE_ID))
        return -1;

    data = malloc(length);
    if (data != NULL)
    {
        memcpy(data, section, length);

        // try to put into queue 3 time
        for (i=0; i<3; i++)
        {
            if (ap_thai_queue_put(data, length))
                break;
        }
        
        if (i == 3)
        {
            free(data);
            data = NULL;
        }
    }

    // send msg to notify ctrl task process data
    ap_send_msg(CTRL_MSG_SUBTYPE_CMD_THAI_SECTION_ARRIVED, 0, 0);
    return 0;
}

UINT32 ap_thai_sdt_monitor_start(struct dmx_device *dmx)
{
    UINT32 ret = INVALID_SIM_ID;

    if (g_thai_sdt_monitor != INVALID_SIM_ID)
    {
        return g_thai_sdt_monitor;
    }
    ret = sim_start_monitor(dmx, MONITE_TB_SDT, 0x0011, 0);

    if (ret == INVALID_SIM_ID)
    {
        return ret;
    }

    g_thai_sdt_monitor = ret;

    if (sim_register_scb(g_thai_sdt_monitor, ap_thai_sdt_callback, NULL) != SUCCESS)
    {
        ap_thai_nit_monitor_stop();
        g_thai_sdt_monitor = INVALID_SIM_ID;
        return INVALID_SIM_ID;
    }

    return ret;
}

void ap_thai_sdt_monitor_stop()
{

    if (INVALID_SIM_ID != g_thai_sdt_monitor)
    {
        sim_unregister_scb(g_thai_sdt_monitor, ap_thai_sdt_callback);
        sim_stop_monitor(g_thai_sdt_monitor);
        g_thai_sdt_crc32 = 0;
        g_thai_sdt_monitor = INVALID_SIM_ID;
    }
}

static void ap_thai_chan_list_reset()
{
    int i=0; 

    for (i=0; i<MAX_THAI_CHANNEL_LIST_SUPPORT; i++)
    {
        if (g_thai_chan_list.plist[i])
        {
            free(g_thai_chan_list.plist[i]);
            g_thai_chan_list.plist[i] = NULL;
        }
    }

    memset(&g_thai_chan_list, 0, sizeof(thai_lcn_list));
}

static thai_lcn_list_info *ap_thai_get_chan_list(UINT8 ch_id)
{
    int i = 0;
    thai_lcn_list_info *ret = NULL;

    
    for (i=0; i<g_thai_chan_list.count; i++)
    {
        if (g_thai_chan_list.plist[i]->chan_list_id == ch_id)
            ret = g_thai_chan_list.plist[i];
    }

    return ret;
}

static thai_lcn_list_info *ap_thai_new_chan_list(UINT8 ch_id)
{
    thai_lcn_list_info *list;

    
    if (g_thai_chan_list.count >= MAX_THAI_CHANNEL_LIST_SUPPORT)
        return NULL;

    list = (thai_lcn_list_info*)malloc(sizeof(thai_lcn_list_info)); 

    if (list == NULL)
        return NULL;

    memset(list, 0, sizeof(thai_lcn_list_info));
    g_thai_chan_list.plist[g_thai_chan_list.count] = list;
    g_thai_chan_list.count++;

    return list;
}

static BOOL ap_thai_lock_tp(UINT32 tp_id)
{
    struct nim_device *nim = NULL;
    UINT32 nim_sub_type = 0;
    T_NODE t_node;
    UINT8 signal_lock= 0;
    union ft_xpond xpond_info;
	int i;
    UINT8 lock_cnt = 0;
    
    nim = dev_get_by_id(HLD_DEV_TYPE_NIM, 0);
    nim_sub_type = dev_get_device_sub_type(nim, HLD_DEV_TYPE_NIM);

    get_tp_by_id(tp_id, &t_node);
    

	xpond_info.t_info.type = FRONTEND_TYPE_T;
	xpond_info.t_info.frq = t_node.frq;
	xpond_info.t_info.sym = t_node.sym;
	xpond_info.t_info.t2_signal = t_node.t2_signal;
	xpond_info.t_info.band_width = (t_node.bandwidth*1000);
	xpond_info.t_info.modulation = 0;

	/*janzy@20150109,decrease retry times for speed up display video*/
	for(i=0;i<ntp_id_Cnt;i++)
	{
		if(g_tp_id[i] == tp_id)
		{
			if (g_islock[i] == FALSE) 
				return FALSE;
			else				
				return TRUE;
		}
	}

    while (lock_cnt < 1) 
    {
        frontend_set_nim(nim, NULL, &xpond_info, 1);
        osal_task_sleep(1000);
        nim_get_lock(nim, &signal_lock);
        
		if (signal_lock==FALSE) 
			thai_ttc_print("%d,tp_id = %d,try lock frq = %d...\n",lock_cnt,tp_id,xpond_info.t_info.frq);
		else
			break;

        lock_cnt++;
    }

	g_tp_id[ntp_id_Cnt] = tp_id;
	g_islock[ntp_id_Cnt] = signal_lock;
	
	if(ntp_id_Cnt >= MAX_LOCK_CNT)
		ntp_id_Cnt = 0;	
	else
		ntp_id_Cnt++;

    if (signal_lock != TRUE) 
        return FALSE;

    return TRUE;
}

static BOOL ap_thai_get_signal_level(UINT32 tp_id, UINT16 *level)
{
	BOOL ret = FALSE;
	struct nim_device *nim = NULL;
	UINT32 nlevel;
	int lock_cnt;
	int i;

    nim = dev_get_by_id(HLD_DEV_TYPE_NIM, 0);
    if (ap_thai_lock_tp(tp_id))
    {
		if(NULL != nim->do_ioctl)
		{
			nlevel = 0;
			lock_cnt = 0;
			
			while (lock_cnt < 2) /*janzy@20150108,decrease retry times for speed up display video*/
			{
				nim->do_ioctl(nim, NIM_DRIVER_GET_AGC, &nlevel);
				if(nlevel <= 0)
					osal_task_sleep(50);
				else
				{
					*level = (UINT16)nlevel;
					ret = TRUE;
					break;
				}
				lock_cnt++;
			}
		}

			
    }
	
    return ret;
}

static BOOL ap_thai_lcn_desc(UINT8 *desc_data, UINT8 len, thai_lcn_list *list)
{
    BOOL ret = FALSE;
    UINT16 service_id = 0;
    BOOL   visible_flag = FALSE;
    UINT16 lcn = 0;
    UINT8 *p = NULL;
    UINT8 *p_end = NULL;
    INT32 idx = 0;
    UINT8 chan_id = 0;
    thai_lcn_list_info *ch_list;
    
    int i,j,count;
    
    p = desc_data;
    p_end = p+len;

    ch_list = ap_thai_get_chan_list(chan_id);

    if (ch_list == NULL)
    {
        if ((ch_list = ap_thai_new_chan_list(chan_id)) == NULL)
        {
            thai_ttc_print("ERROR: new channel list failed\n");
            return ret;
        }
    }
    
    while (p<p_end)
    {
        service_id = (p[0]<<8)|p[1];
        p += 2;
        visible_flag = FALSE;
        if (p[0]>>7)
        {
            visible_flag = TRUE;
        }
        lcn = ((p[0]&0x03)<<8)|p[1];
        p += 2;
        thai_ttc_print("NIT SID 0x%04x, visible %d, LCN %04d\n", service_id, visible_flag, lcn);

        idx = ch_list->count;
        if (idx >= MAX_THAI_SERVICE_PER_LIST)
        {
            thai_ttc_print("ERROR: too many service in lcn desc\n");
            break;
        }
        ch_list->lcn_list[idx].lcn = lcn;
        ch_list->lcn_list[idx].visible = visible_flag;
        ch_list->lcn_list[idx].sid = service_id;
        ch_list->count++;
        ret = TRUE;
    }
#if(AOV_TTC_SUBTITLE_SUPPORT_ENABLE == SYS_FUNC_ON)
	for(i=0;i<ch_list->count;i++)
	{			
		count = 0;
		for(j=0;j<ch_list->count;j++)
		{
			if((ch_list->lcn_list[i].lcn == ch_list->lcn_list[j].lcn) && i != j)
			{
				count++;
				break;
			}
		}
		if( count > 0 )
			break;
	}
	if( count > 0)
		nDoLCNForeign = 1;
	else
		nDoLCNForeign = 0;
#endif

    return ret;
}

static BOOL ap_thai_lcn_desc_v2(UINT8 *desc_data, UINT8 len, thai_lcn_list *list)
{
    BOOL ret = FALSE;
    UINT16 service_id = 0;
    BOOL   visible_flag = FALSE;
    UINT16 lcn = 0;
    UINT8 *p = NULL;
    UINT8 *p_end = NULL;
    UINT8 *p_desc_loop_end = NULL;
    INT32 idx = 0;
    UINT8 chan_id = 0;
    UINT8 name_len = 0;
    UINT8 desc_loop_len = 0;
    thai_lcn_list_info *ch_list;
	T_NODE tnode;
	int count;
	int i,j;

    
    thai_ttc_print_line;

    p = desc_data;
    p_end = p + len;

    // list loop
    while (p < p_end)
    {
        chan_id = p[0];
        p++;
        name_len = p[0];
        p++;

        ch_list = ap_thai_get_chan_list(chan_id);
        if (ch_list == NULL)
        {
            if ((ch_list = ap_thai_new_chan_list(chan_id)) == NULL)
            {
                thai_ttc_print("ERROR: new channel list failed\n");
                return ret;
            }
        }

        memcpy(ch_list->list_name, p, name_len);
        p += name_len;
        memcpy(ch_list->country_code, p, 3);
        p += 3;
       
        desc_loop_len = p[0];
        p++;

        p_desc_loop_end = p + desc_loop_len;

        while (p < p_desc_loop_end)
        {
            service_id = (p[0]<<8)|p[1];
            p += 2;
            visible_flag = FALSE;
            if (p[0]>>7)
            {
                visible_flag = TRUE;
            }
            lcn = ((p[0]&0x03)<<8)|p[1];
            p += 2;
            thai_ttc_print("NIT v2 SID %d, visible %d, LCN %d\n", service_id, visible_flag, lcn);

            idx = ch_list->count;
            if (idx >= MAX_THAI_SERVICE_PER_LIST)
            {
                thai_ttc_print("ERROR: too many service in lcn desc\n");
                break;
            }
            ch_list->lcn_list[idx].lcn = lcn;
            ch_list->lcn_list[idx].visible = visible_flag;
            ch_list->lcn_list[idx].sid = service_id;
            ch_list->count++;
            ret = TRUE;
        }
#if(AOV_TTC_SUBTITLE_SUPPORT_ENABLE == SYS_FUNC_ON)
		for(i=0;i<ch_list->count;i++)
		{			
			count = 0;
			for(j=0;j<ch_list->count;j++)
			{
				if((ch_list->lcn_list[i].lcn == ch_list->lcn_list[j].lcn) && i != j)
				{
					count++;
					break;
				}
			}
			if( count > 0 )
				break;
		}
		if(	count > 0)
			nDoLCNForeign = 1;
		else
			nDoLCNForeign = 0;
#endif		
    }

    return ret;
}

static thai_prog_list* ap_thai_create_prog_list()
{
	UINT16 count;
	INT32 er;
	INT32 i,j;
	P_NODE node;
	thai_prog_lcn_info *list = NULL;
	thai_prog_list *prog_list;
	UINT8 cnamet[2*(MAX_SERVICE_NAME_LENGTH + 1)];			//36
	int c;
	int c_sum;
	T_NODE tnode;
    recreate_prog_view(VIEW_ALL|PROG_TVRADIO_MODE,0);
    count = get_prog_num(VIEW_ALL | PROG_TVRADIO_MODE,0);

    if (count == 0)
        return NULL;
    
    if (count > 0)
    {
        list = malloc(sizeof(thai_prog_lcn_info)*count);
        if (list == NULL)
        {
            return NULL;
        }
    }
    
    for(i=0; i<count; i++)
    {
        er = get_prog_at(i, &node);
        if(SUCCESS != er)
        {
            free(list);
            list = NULL;
            return NULL;
        }

		list[i].lcn = node.LCN;
		list[i].sid = node.prog_number;
		list[i].tp_id = node.tp_id;
		list[i].visible = node.visible_flag;
		list[i].orig_lcn = node.orig_LCN;

		list[i].service_type = node.service_type;
		list[i].name_len = node.name_len;
		memcpy(list[i].service_name, node.service_name, node.name_len);

		thai_ttc_print_line;
		list[i].av_flag = node.av_flag;
		get_tp_by_id(list[i].tp_id, &tnode);

		if ((node.service_type == SERVICE_TYPE_HD_MPEG2) 
		|| (node.service_type == SERVICE_TYPE_HD_MPEG4))
		{
			list[i].hd_service = 1;
		}
		else
		{
			list[i].hd_service = 0;
		}
		list[i].onid = tnode.network_id;
		
    }

    prog_list = malloc(sizeof(thai_prog_list));
    prog_list->list = list;
    prog_list->count = count;
    return prog_list;
}

static UINT32 ap_thai_get_tp_id(UINT16 onid, UINT16 tsid)
{
    T_NODE tnode;
    UINT16 count;
    INT32 i;
    UINT16 sat_id;
    UINT32 tp_id = 0;
    
    if (ap_thai_get_current_tp(&tnode) == FALSE)
    {
        return 0;
    }

    sat_id = tnode.sat_id;
    
    count = get_tp_num_sat(sat_id);

    for (i=0; i<count; i++)
    {
        get_tp_at(sat_id, i, &tnode);	
        if ((tp_id == 0)&&(tnode.network_id == onid) && (tnode.t_s_id == tsid))
        {
            tp_id =  tnode.tp_id;
        }
    }

    return tp_id;    
}

static INT32 ap_thai_get_prog_idx(thai_prog_list *list, UINT32 tp_id, UINT16 sid)
{
    INT32 ret = -1;
    int i=0; 

    for (i=0; i<list->count; i++)
    {
        if (list->list[i].tp_id == tp_id && list->list[i].sid == sid)
        {
            ret = i;
            break;
        }
    }

    return ret;
}

static INT32 ap_thai_get_prog_by_lcn(thai_prog_list *list,UINT16 lcn)
{
    INT32 ret = -1;
    int i=0; 

    for (i=0; i<list->count; i++)
    {
#if(AOV_TTC_SUBTITLE_SUPPORT_ENABLE == SYS_FUNC_ON)
	if (list->list[i].orig_lcn == lcn)/*janzy@20141225,lcn to orig_lcn*/
#else
        if (list->list[i].lcn == lcn)
#endif
        {
            ret = i;
            break;
        }
    }

    return ret;
}

//#define THAILAND_ONID 0x233A
static UINT16 ap_thai_get_max_lcn(thai_prog_list *list)
{
    INT32 i;
    UINT16 max_lcn = 0;

    for (i=0; i<list->count; i++)
    {
        if (list->list[i].lcn > max_lcn)
        {
            max_lcn = list->list[i].lcn;
        }
    }

    if (max_lcn < THAILAND_LCN_CONFLICT_RANGE_BEGIN)
    {
        max_lcn = THAILAND_LCN_CONFLICT_RANGE_BEGIN-1;
    }
    
    return max_lcn;
}

//#define  THAILAND_ONID 0x7FFE

static BOOL ap_thai_lcn_conflict_proc(thai_prog_list *prog_list, INT32 idx1, INT32 idx2, UINT16 idx1_new_lcn)
{
    BOOL bupdate = FALSE;
    T_NODE tnode1, tnode2;
    P_NODE pnode;
    UINT16 lcn_tmp = 0;
    UINT8 quality1 = 0;
    UINT8 quality2 = 0;

	int i,j;
	int ii,jj;

    get_tp_by_id(prog_list->list[idx1].tp_id, &tnode1);
    get_tp_by_id(prog_list->list[idx2].tp_id, &tnode2);

    
    if ((tnode1.tp_id != tnode2.tp_id) && (tnode1.network_id == tnode2.network_id))
    {
        if (tnode1.intensity >= tnode2.intensity )
        {
            // no need swap
            return FALSE;
        }
        
        get_prog_at(idx1, &pnode);

        lcn_tmp = pnode.LCN;
        pnode.LCN = idx1_new_lcn;
        prog_list->list[idx1].lcn = idx1_new_lcn;

        modify_prog(pnode.prog_id, &pnode);
        update_data();

        lcn_tmp = ap_thai_get_max_lcn(prog_list);
        lcn_tmp ++;
        
        get_prog_at(idx2, &pnode);
        pnode.LCN = lcn_tmp;
        prog_list->list[idx2].lcn = lcn_tmp;
        modify_prog(pnode.prog_id, &pnode);
        update_data();

        bupdate = TRUE;
    }
    else if (tnode1.tp_id == tnode2.tp_id)
    {
        if(nDoLCNForeign > 0)
        {
			// just put new change LCN to 800~
			get_prog_at(idx1, &pnode);
			lcn_tmp = ap_thai_get_max_lcn(prog_list);
			lcn_tmp ++;
			pnode.LCN = lcn_tmp;
			prog_list->list[idx1].lcn = lcn_tmp;
			modify_prog(pnode.prog_id, &pnode);
		}
		else
		{

			for(ii=0;ii<AOV_ch_list->count;ii++)
				for(jj=0;jj<prog_list->count;jj++)
						if( AOV_ch_list->lcn_list[ii].sid == prog_list->list[jj].sid &&
							AOV_ch_list->lcn_list[ii].lcn != prog_list->list[jj].lcn)
								{
									get_prog_at(jj, &pnode);
									pnode.LCN = AOV_ch_list->lcn_list[ii].lcn;
									prog_list->list[jj].lcn = AOV_ch_list->lcn_list[ii].lcn;
									modify_prog(pnode.prog_id, &pnode);
									break;
								}
			
		}

		update_data();
		bupdate = TRUE;
    }
    else
    {
        if (tnode1.network_id == THAILAND_ONID && tnode2.network_id != THAILAND_ONID)
        {
            // swap
            get_prog_at(idx1, &pnode);
            pnode.LCN = idx1_new_lcn;
            prog_list->list[idx1].lcn = idx1_new_lcn;
            modify_prog(pnode.prog_id, &pnode);
            update_data();
            lcn_tmp = ap_thai_get_max_lcn(prog_list);
            lcn_tmp ++;
            get_prog_at(idx2, &pnode);

            pnode.LCN = lcn_tmp;
            prog_list->list[idx2].lcn = lcn_tmp;
            
            modify_prog(pnode.prog_id, &pnode);
            update_data();
            bupdate = TRUE;
        }
        else if (tnode1.network_id != THAILAND_ONID && tnode2.network_id == THAILAND_ONID)
        {
            // no swap
            lcn_tmp = ap_thai_get_max_lcn(prog_list);
            lcn_tmp ++;
            get_prog_at(idx1, &pnode);
            pnode.LCN = lcn_tmp;
            prog_list->list[idx1].lcn = lcn_tmp;         
            modify_prog(pnode.prog_id, &pnode);
            update_data();

            bupdate = TRUE;
        }
        else if (tnode1.network_id != THAILAND_ONID && tnode2.network_id != THAILAND_ONID)
        {
            get_prog_at(idx1, &pnode);
            lcn_tmp = pnode.LCN;
            pnode.LCN = idx1_new_lcn;
            prog_list->list[idx1].lcn = idx1_new_lcn;
            modify_prog(pnode.prog_id, &pnode);
            update_data();
            get_prog_at(idx2, &pnode);
            pnode.LCN = lcn_tmp;       
            modify_prog(pnode.prog_id, &pnode);
            update_data();
            bupdate = TRUE;
        }
    }

    return bupdate;
}
static void print_prog_list(  thai_prog_list *prog_list   )
{
    INT32 i = 0;	 
    for (i=0; i<prog_list->count; i++)
    {
		thai_ttc_print("--LCN [%5d], O_LCN[%5d], SID %04X, s_type %2x\n",   prog_list->list[i].lcn, prog_list->list[i].orig_lcn,prog_list->list[i].sid,prog_list->list[i].service_type);
    }	
	return;
}
static void ap_thai_lcn_check(INT32 ch_idx)
{
    thai_lcn_list_info *ch_list = NULL;
    thai_prog_list *prog_list = NULL;
    INT32 i = 0,ii;
    INT32 j = 0,jj;
    UINT16 tp_id = 0;
    INT32 idx = 0;
    INT32 idx2 = 0;
    P_NODE pnode;
    T_NODE tnode;
    BOOL bupdate = FALSE;
    BOOL bret = FALSE;


	
    ch_list = g_thai_chan_list.plist[ch_idx];
	AOV_ch_list = g_thai_chan_list.plist[ch_idx];

    // create db infor
    prog_list = ap_thai_create_prog_list();

    if (prog_list == NULL)
    {
        return ;
    }

    tp_id = ap_thai_get_tp_id(g_thai_chan_list.onid, g_thai_chan_list.tsid);
    
    for (i=0; i<ch_list->count; i++)
    {
        // get the pnode
        idx = ap_thai_get_prog_idx(prog_list, tp_id, ch_list->lcn_list[i].sid);

        if (idx < 0)		
            continue;

        
        // check visible
        if (ch_list->lcn_list[i].visible != prog_list->list[idx].visible)
        {
            // update visible
            get_prog_at(idx, &pnode);
            pnode.visible_flag = ch_list->lcn_list[i].visible;
            prog_list->list[idx].visible = ch_list->lcn_list[i].visible;
            modify_prog(pnode.prog_id, &pnode);
            update_data();
            bupdate = TRUE;
        }

        // check lcn
        if (ch_list->lcn_list[i].lcn != prog_list->list[idx].lcn)
        {
            // if ch_list->lcn_list[i].lcn == 0  new lcn == 0 , need del this service
            get_tp_by_id(tp_id, &tnode);

            if ((prog_list->list[idx].lcn >= THAILAND_LCN_CONFLICT_RANGE_BEGIN ) && (tnode.network_id != THAILAND_ONID))
                continue;
                
            // if program in nit not the same lcn with DB, find out the conflict program
            idx2 = ap_thai_get_prog_by_lcn(prog_list, ch_list->lcn_list[i].lcn);

            if (idx2 < 0)
            {
                // This case, the program was put into conflict range, but new LCN no one use, so just use new LCN
                get_prog_at(idx, &pnode);
                pnode.LCN = ch_list->lcn_list[i].lcn;
                prog_list->list[idx].lcn = ch_list->lcn_list[i].lcn;
                modify_prog(pnode.prog_id, &pnode);
                update_data();
                bupdate = TRUE;
				
            }
            else  if ((idx2>=0) && (prog_list->list[idx].lcn >= THAILAND_LCN_CONFLICT_RANGE_BEGIN))
            {
				AOV_DBG_PRINT(("no swap"));
                // no swap
            }
            else
            {

                bret = ap_thai_lcn_conflict_proc(prog_list, idx, idx2, ch_list->lcn_list[i].lcn);
                if (bret)
                {
                    bupdate = bret;					
                }
            }
        }
        
    }
    
    free(prog_list->list);
    free(prog_list);   
    
    if (bupdate)
    {
        if(sys_data_get_LCN())
        {
			sort_prog_node(PROG_LCN_SORT);
			update_data();
			// send msg
			ap_send_msg(CTRL_MSG_SUBTYPE_CMD_UPDATE_VIEW, 0, FALSE);
			ap_thai_sort_after_search();
        }
    }


}


static void ap_thai_nit_parse(UINT8 *section, INT32 length, thai_lcn_list *list)
{
    UINT16 len = 0;
    UINT16 desc_loop_len = 0;
    UINT16 tsid = 0;
    UINT16 onid = 0;
    UINT8 *p = NULL;
    UINT8 *p_end = NULL;
    UINT8 *p_desc_loop_end = NULL;
    UINT8 desc_tag = 0;
    UINT8 desc_len = 0;
    
    LCL_Verion = 0;
    // goto loop2
    if (length < 10)
    {
        return;
    }

    p = section + 8;
    len = ((p[0]&0x0F)<<8)|p[1];  // loop1 length
    p += 2;

    p += len;

    len = ((p[0]&0x0F)<<8)|p[1]; // loop2 length
    p += 2;

    p_end = p + len;
    while (p < p_end)
    {
        tsid = (p[0]<<8)|p[1];
        p += 2;
        onid = (p[0]<<8)|p[1];
        p += 2;
        desc_loop_len = ((p[0]&0x0F)<<8)|p[1]; 
        p += 2;

        list->onid = onid;
        list->tsid = tsid;
 
        p_desc_loop_end = p + desc_loop_len;
        while (p < p_desc_loop_end)
        {
            desc_tag = p[0];
            desc_len = p[1];
            p += 2;
            if (desc_tag == LOGICAL_CHANNEL_NUMBER_DESCRIPTOR)
            {
                ap_thai_lcn_desc(p, desc_len, list);
				
				LCL_Verion = 1;
            }
            if (desc_tag == LOGICAL_CHANNEL_NUMBER_DESCRIPTOR_V2)
            {
                ap_thai_lcn_desc_v2(p, desc_len, list);
				
				LCL_Verion = 2;
            }
            p += desc_len;
        }

    }
    
}

static void ap_thai_sdt_slist_reset()
{
    memset(&g_thai_sdt_slist, 0, sizeof(thai_sdt_serv_list));
}



static void ap_thai_service_descriptor(UINT8 *data, UINT8 length, thai_sdt_serv_list *slist)
{
    UINT8 stype = 0;
    UINT8 len;
    UINT8 *p = data;
    UINT8 name[256] = {0};
    UINT8 k;
    
    stype = p[0];
    len = p[1];
    p += 2;
    p += len;

    len = p[0];
    p++;

    slist->list[slist->serv_count].service_type = stype;
    memcpy(name, p, len);

    len = dvb_to_unicode(name, len, slist->list[slist->serv_count].service_name, MAX_SERVICE_NAME_LENGTH, 11);
    slist->list[slist->serv_count].name_len = len*2;
    
}
static void ap_thai_sdt_parse(UINT8 *section, INT32 length, thai_sdt_serv_list *slist)
{
    UINT8 *p;
    UINT8 *p_end;
    UINT8 *p_desc_loop_end;
    UINT16 onid;
    UINT16 tsid;
    UINT16 sid;
    UINT16 subLen;
    UINT8 tag;
    UINT8 desc_len;
    
    p = section;
    p_end = p + length -4;
    
    p += 3;
    tsid = (p[0]<<8)|p[1];
    p += 2;

    p += 3;
    onid = (p[0]<<8)|p[1];
    p += 2;
    p += 1;

    slist->onid = onid;
    slist->tsid = tsid;
    while (p<p_end)
    {
        sid = (p[0]<<8)|p[1];
        p += 2;
        p += 1;
        subLen = ((p[0]&0x0f)<<8)|p[1];
        p += 2;
        p_desc_loop_end = p + subLen;
        slist->list[slist->serv_count].sid = sid;
        while (p<p_desc_loop_end)
        {
            tag = p[0];
            desc_len = p[1];
            p += 2;

            if (tag == SERVICE_DESCRIPTOR)
            {
                ap_thai_service_descriptor(p, desc_len, slist);
            }
            p += desc_len;
        }
        slist->serv_count++;
    }
    
    
}
static UINT8 ap_thai_check_service_av(UINT8 type)
{
    UINT8 av_flag = 0;

    switch (type)
    {
        case SERVICE_TYPE_DTV:
        case SERVICE_TYPE_SD_MPEG4:
        case SERVICE_TYPE_HD_MPEG2:
        case SERVICE_TYPE_HD_MPEG4:
            av_flag = 1;
            break;
        case SERVICE_TYPE_DRADIO:
        case SERVICE_TYPE_FMRADIO:
            av_flag = 0;
            break;
    }

    return av_flag;
}

static void ap_thai_service_check()
{
    thai_prog_list *prog_list = NULL;
    INT32 i = 0;
    INT32 j = 0;
    UINT16 tp_id = 0;
    INT32 idx = 0;
    INT32 idx2 = 0;
    P_NODE pnode;
    UINT8 av_flag = 0;
    BOOL bupdate = FALSE;

    // create db infor
    prog_list = ap_thai_create_prog_list();

    if (prog_list == NULL)
    {
        return ;
    }
    tp_id = ap_thai_get_tp_id(g_thai_sdt_slist.onid, g_thai_sdt_slist.tsid);
    for (i=0; i<g_thai_sdt_slist.serv_count; i++)
    {
        idx = ap_thai_get_prog_idx(prog_list, tp_id, g_thai_sdt_slist.list[i].sid);

        if (idx <0)
        {
            continue;
        }
		
        // check service name
        if ((prog_list->list[idx].name_len != g_thai_sdt_slist.list[i].name_len)
        || (memcmp(prog_list->list[idx].service_name, g_thai_sdt_slist.list[i].service_name, g_thai_sdt_slist.list[i].name_len)!=0))
        {
 
            bupdate = TRUE;	
        }

        av_flag = ap_thai_check_service_av(g_thai_sdt_slist.list[i].service_type);

        if (av_flag != prog_list->list[idx].av_flag)
        {
            bupdate = TRUE;
        }

        if (bupdate)
        {
            get_prog_at(idx, &pnode);
            pnode.name_len = g_thai_sdt_slist.list[i].name_len;
            pnode.av_flag = av_flag;
            prog_list->list[idx].av_flag = av_flag;
            memcpy(pnode.service_name, g_thai_sdt_slist.list[i].service_name, pnode.name_len);
            modify_prog(pnode.prog_id, &pnode);
            update_data();

            // send msg
            ap_send_msg(CTRL_MSG_SUBTYPE_CMD_UPDATE_VIEW, 0, FALSE);
 
        }
    }

    free(prog_list->list);
    free(prog_list);
}

// process message in ap_control_task
void ap_thai_monitor_msg_proc(UINT32 type, UINT32 code)
{
    UINT8 *section;
    INT32 length;
    UINT32 crc32 = 0;
    INT32 chan_list_idx = 0;
    UINT8 group_idx = 0;
    INT32 i;
	SYSTEM_DATA * sys;
	static int nprintf = 0;


    if (type != CTRL_MSG_SUBTYPE_CMD_THAI_SECTION_ARRIVED)
    {
        return ;
    }

    while ((section = ap_thai_queue_get(&length)) != NULL)
    {
        crc32 = (section[length-4]<<24)|(section[length-3]<<16)|(section[length-2]<<8)|(section[length-1]);
        if (section[0] == PSI_NIT_TABLE_ID)
        {
 
			if(nprintf > 10)
			{
				nprintf = 0;
				AOV_TCC_Subtitle_language();
			}
			else
				nprintf++;
				
            if (crc32 != g_thai_nit_crc32)
            {
				g_thai_nit_crc32 = crc32;
				AOV_TCC_Subtitle_language();

				ap_thai_chan_list_reset();
				ap_thai_nit_parse(section, length, &g_thai_chan_list);
				if (g_thai_chan_list.count >= 2)
				{
                    // maybe we should let user select the channel list
                    chan_list_idx = 0;
                    for (i=0; i<g_thai_chan_list.count; i++)
                    {

                        if (memcmp(g_thai_chan_list.plist[i]->country_code, "THA", 3)==0)
                        {
                            chan_list_idx = i;
                            break;
                        }
                    }
                }

                if (g_thai_chan_list.count > 0)
                    ap_thai_lcn_check(chan_list_idx);

                group_idx = sys_data_get_cur_group_index();
                sys_data_change_group(group_idx);

            }
        }
        else if (section[0] == PSI_SDT_TABLE_ID)
        {

            if (crc32 != g_thai_sdt_crc32)
            {

                AOV_TCC_Subtitle_language();
                g_thai_sdt_crc32 = crc32;
                ap_thai_sdt_slist_reset();
                ap_thai_sdt_parse(section, length, &g_thai_sdt_slist);
                ap_thai_service_check();
                group_idx = sys_data_get_cur_group_index();
                sys_data_change_group(group_idx);
            }
        }

        free(section);
        section = NULL;
    }
}

// after search program, need check if there are any programs is the actual same, and pk signal quality
// to determine the LCN.
void ap_thai_sort_after_search()
{
    thai_prog_list *prog_list = NULL;
    T_NODE tnode1, tnode2;
    P_NODE pnode;
    UINT8 q1 = 0, q2 = 0;
    UINT16 lcn_tmp = 0;
    BOOL bupdate = FALSE;
    int i, j, k;
    UINT32 *del_list = NULL;
    INT32 del_cnt = 0;
    UINT16 *hd_list = NULL;
    INT32  hd_cnt = 0;
    UINT16 *sd_list = NULL;
    INT32  sd_cnt = 0;
    UINT16 *radio_list = NULL;
    INT32  radio_cnt = 0;

	ntp_id_Cnt = 0;
     
    prog_list = ap_thai_create_prog_list();

    thai_ttc_print_line;
    if (prog_list == NULL)
    {
        return;
    }

    thai_ttc_print_line;

    del_list = (UINT32*)malloc(prog_list->count*sizeof(UINT32));
    del_cnt = 0;
    MEMSET(del_list, 0, prog_list->count*sizeof(UINT32));

    // rule: ONID is thailand, the same stream's program, but in different tp, need pk signal
    //       and delete signal weak's program
    for (i=0; i<prog_list->count; i++)
    {
        for (j=0; j<prog_list->count; j++)
        {
            {
                // the actual same stream and program with ONID THAILAND, need pk signal
                if ((prog_list->list[i].orig_lcn == prog_list->list[j].orig_lcn)
                && (prog_list->list[i].sid == prog_list->list[j].sid)
                && (prog_list->list[i].tp_id != prog_list->list[j].tp_id))
                {
                    // maybe we need compare signal 
                    get_tp_by_id(prog_list->list[i].tp_id, &tnode1);
                    get_tp_by_id(prog_list->list[j].tp_id, &tnode2);
   

					/*janzy@20141230,fixed TT1604#the same stream and change channel frequency then program can't display.
						1. auto scan
						2. change frequency, 858Mhz -> 850Mhz
						3. Manual Scan 850Mhz
					*/
					UINT16 intensity;
					intensity = 0;
					if(ap_thai_get_signal_level(tnode1.tp_id, &intensity) == TRUE)
 						tnode1.intensity = intensity;
					else
						tnode1.intensity = 0;

					intensity = 0;
					if(ap_thai_get_signal_level(tnode2.tp_id, &intensity) == TRUE)
 						tnode2.intensity = intensity;
					else
						tnode2.intensity = 0;

					if(tnode2.intensity > tnode1.intensity)
						ap_thai_lock_tp(tnode2.tp_id);
					else
						ap_thai_lock_tp(tnode1.tp_id);
					/*janzy@20141230,end*/
              
                    if ((tnode1.t_s_id == tnode2.t_s_id) && (tnode1.network_id == tnode2.network_id))
                    {

                        if (tnode1.intensity < tnode2.intensity)
                        {
                            // need delete i program
                            if ((prog_list->list[i].lcn < THAILAND_LCN_CONFLICT_RANGE_BEGIN)
                            && (prog_list->list[j].lcn >= THAILAND_LCN_CONFLICT_RANGE_BEGIN))
                            {
                                // need swap , keep i's LCN
                                get_prog_at(j, &pnode);
                                pnode.LCN = prog_list->list[i].lcn;
                                prog_list->list[j].lcn = prog_list->list[i].lcn;
                                modify_prog(pnode.prog_id, &pnode);
                            }

                            get_prog_at(i, &pnode); // signal weak, to be deleted
                            lcn_tmp = pnode.LCN;
                            pnode.LCN = 0;//lcn_tmp;
                            prog_list->list[i].lcn = 0;//lcn_tmp;
                            modify_prog(pnode.prog_id, &pnode);

                            del_list[del_cnt] = pnode.prog_id;
                            del_cnt++;
                            bupdate = TRUE;
                        }
                    }
                }
            }
        }
    }

    // delete program
    if (del_cnt > 0)
    {
        for (i=0; i<del_cnt; i++)
        {
            del_prog_by_id(del_list[i]);
        }
        update_data();
        free(prog_list->list);
        free(prog_list);

        // create list again
        prog_list = ap_thai_create_prog_list();
    }


    thai_prog_lcn_info *progI, *progJ;
    BOOL bswap = FALSE;
    
    // check conflic HD>SD>Radio
    for (i=0; i<prog_list->count; i++)
    {
        thai_ttc_print_line;
        for (j=0; j<prog_list->count; j++)
        {
            bswap = FALSE;
            progI = &prog_list->list[i];
            progJ = &prog_list->list[j];

            if ((j 				!= i) 
            && (progI->lcn 		>= THAILAND_LCN_CONFLICT_RANGE_BEGIN)
            && (progJ->lcn 		<  THAILAND_LCN_CONFLICT_RANGE_BEGIN)
            && (progI->orig_lcn == progJ->lcn))
            {
                if ((progI->av_flag == 1) && (progJ->av_flag == 0)) // TV vs Radio
                    bswap = TRUE;

                else if ((progI->hd_service == 1) && (progJ->hd_service == 0)) // HD vs SD
                    bswap = TRUE;

            }


            if (bswap == TRUE)
            {
            	if(prog_list->list[i].onid != THAILAND_ONID && prog_list->list[i].lcn >= THAILAND_LCN_CONFLICT_RANGE_BEGIN)
			bswap = FALSE;
            }

			
            if (bswap)
			{
				get_prog_at(i, &pnode);
				lcn_tmp = pnode.LCN;
				pnode.LCN = progJ->lcn;
				progI->lcn = progJ->lcn;
				modify_prog(pnode.prog_id, &pnode);
				
				osal_task_sleep(100);
				
				get_prog_at(j, &pnode);
				pnode.LCN = lcn_tmp;
				progJ->lcn = lcn_tmp;
				modify_prog(pnode.prog_id, &pnode);
				
				osal_task_sleep(100);
				
				bupdate = TRUE;
			}
        }
    }

    if (bupdate)
    {
		bupdate = FALSE;
		sort_prog_node(PROG_LCN_SORT);
		update_data();
		free(prog_list->list);
		free(prog_list);
		
		// create list again
		prog_list = ap_thai_create_prog_list();	
   }

    // rule: sort from 800, HD>SD>Radio
    // get hd list
    hd_list = (UINT16*)malloc(sizeof(UINT16)*256);
    

    for (i=0; i<prog_list->count; i++)
    {
        if ((prog_list->list[i].lcn >= THAILAND_LCN_CONFLICT_RANGE_BEGIN) 
        && (prog_list->list[i].hd_service)
        && (prog_list->list[i].av_flag))
        {
            hd_list[hd_cnt] = i;
            hd_cnt++;
            for (k=0; k<prog_list->list[i].name_len; k++)
            {
                if (prog_list->list[i].service_name[k])
                {
                	if(isprint(prog_list->list[i].service_name[k]))
	                    thai_ttc_print("%c", prog_list->list[i].service_name[k]);
                }
            }
            thai_ttc_print("\n");
        }
    }

	
    // get sd list
    thai_ttc_print("SD Service: 800~\n");
    sd_list = (UINT16*)malloc(sizeof(UINT16)*256);
    for (i=0; i<prog_list->count; i++)
    {
        if ((prog_list->list[i].lcn >= THAILAND_LCN_CONFLICT_RANGE_BEGIN) 
        && (prog_list->list[i].hd_service==0)
        && (prog_list->list[i].av_flag))
        {
            sd_list[sd_cnt] = i;
            sd_cnt++;
            for (k=0; k<prog_list->list[i].name_len; k++)
            {
                if (prog_list->list[i].service_name[k])
                {
                	if(isprint(prog_list->list[i].service_name[k]))
						thai_ttc_print("%c", prog_list->list[i].service_name[k]);
                }
            }
            thai_ttc_print("\n");
        }
    }
	
    // get radio list

    radio_list = (UINT16*)malloc(sizeof(UINT16)*256);

    lcn_tmp = THAILAND_LCN_CONFLICT_RANGE_BEGIN;

    for (i=0; i<hd_cnt; i++)
    {
        get_prog_at(hd_list[i], &pnode);
        prog_list->list[hd_list[i]].lcn = lcn_tmp;
        if (pnode.LCN != lcn_tmp)
        {
            pnode.LCN = lcn_tmp;
            modify_prog(pnode.prog_id, &pnode);
            bupdate = TRUE;
        }
        lcn_tmp++;
    }

    for (i=0; i<sd_cnt; i++)
    {
        get_prog_at(sd_list[i], &pnode);
        prog_list->list[sd_list[i]].lcn = lcn_tmp;
        if (pnode.LCN != lcn_tmp)
        {
            pnode.LCN = lcn_tmp;
            modify_prog(pnode.prog_id, &pnode);
            bupdate = TRUE;
        }
        lcn_tmp++;
    }

    for (i=0; i<radio_cnt; i++)
    {
        get_prog_at(radio_list[i], &pnode);
        prog_list->list[radio_list[i]].lcn = lcn_tmp;
        if (pnode.LCN != lcn_tmp)
        {
            pnode.LCN = lcn_tmp;
            modify_prog(pnode.prog_id, &pnode);
            bupdate = TRUE;
        }
        lcn_tmp++;
    }

    if (bupdate)
    {
        sort_prog_node(PROG_LCN_SORT);
        update_data();
    }

    if (hd_list)
    {
        free(hd_list);
    }
    if (sd_list)
    {
        free(sd_list);
    }
    if (radio_list)
    {
        free(radio_list);
    }
    free(prog_list->list);
    free(prog_list);
    free(del_list);

//////////////////////////////////
//  for debug, check list
    prog_list = ap_thai_create_prog_list();

    free(prog_list->list);
    free(prog_list);

}


static UINT32 *g_unlock_tp_list = NULL;
static UINT16 g_unlock_tp_cnt = 0;
#define MAX_UNLOCK_TP_NUM_SUPPORT 1024

void ap_thai_reset_unlock_tp_list()
{
    thai_ttc_print_line;
    
    if (g_unlock_tp_list)
    {
        free(g_unlock_tp_list);
        g_unlock_tp_list = NULL;
    }

    g_unlock_tp_cnt = 0;
}

void ap_thai_add_unlock_tp_record(UINT32 frq)
{
    T_NODE tnode;
    UINT16 tp_cnt = 0;
    INT32 i = 0;
    INT32 ret = 0;

    thai_ttc_print_line;
    
    if (g_unlock_tp_list == NULL)
    {
        g_unlock_tp_list = (UINT32*)malloc(MAX_UNLOCK_TP_NUM_SUPPORT*sizeof(UINT32));
        if (g_unlock_tp_list == NULL)
        {
            return;
        }

        g_unlock_tp_cnt = 0;
    }

    tp_cnt = get_tp_num_sat(1);
    thai_ttc_print_line;
    for (i=0; i<tp_cnt; i++)
    {
        ret = get_tp_at(1, i, &tnode);
        if (ret != DB_SUCCES)
        {
            break;
        }

        if (tnode.frq == frq)
        {
            g_unlock_tp_list[g_unlock_tp_cnt] = tnode.tp_id;
            g_unlock_tp_cnt ++;
        }
    }

}

void ap_thai_remove_one_tp_program(UINT32 tp_id)
{
    INT32 cnt = 0;
    INT32 i = 0;
    INT32 j = 0;
    P_NODE pnode;
    BOOL bupdate = FALSE;

    thai_ttc_print_line;

    if (tp_id == 0)
        return;
    
    cnt = get_prog_num(VIEW_ALL|PROG_TVRADIO_MODE, 0);

    for (i=cnt-1; i>=0; i--)
    {
        get_prog_at((UINT16)i, &pnode);
        if (pnode.tp_id == tp_id)
        {
            del_prog_at(i);
            bupdate = TRUE;
        }
    }

    if (bupdate)
    {
        update_data();
        reset_lcn_table_to_view();
    }
    thai_ttc_print_line;
}
void ap_thai_remove_unlock_tp_program()
{
    INT32 cnt = 0;
    INT32 i = 0;
    INT32 j = 0;
    P_NODE pnode;

    thai_ttc_print_line;
    cnt = get_prog_num(VIEW_ALL|PROG_TVRADIO_MODE, 0);

    if (g_unlock_tp_cnt == 0)
    {
        return;
    }
    
    for (i=cnt-1; i>=0; i--)
    {
        get_prog_at((UINT16)i, &pnode);

        for (j=0; j<g_unlock_tp_cnt; j++)
        {
            if (pnode.tp_id == g_unlock_tp_list[j])
            {
                del_prog_at(i);
                break;
            }
        }
    }

    update_data();
}




